﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using TFDP.Common.Services;
using TFDP.VisualStudioInterop;

namespace TFDP.SimpleProcessor
{
    public partial class TemplateMappingsEditorWindow : Form
    {
        private List<TemplateMapping> mappings;
        private BindingSource mappingsSource;
        private BindingSource propertySource;
        private IEnumerable<Type> objectTypes;
        private IEnumerable<Project> projects;
        private IEnumerable<Template> templates;

        public TemplateMappingsEditorWindow(List<TemplateMapping> mappings)
        {
            this.mappings = mappings;

            string activeProject = VsInteropUtilities.GetActiveProject();

            objectTypes = DetermineTypes();

            projects = VsInteropUtilities.GetProjectsInSolution()
                .Select(p => new Project() { Name = p })
                .ToList();

            templates = VsInteropUtilities.GetFilesInDirectory(activeProject, "Templates", (file) => file.EndsWith(".tt"))
                .Select(f => new Template() { Name = f })
                .ToList();

            InitializeComponent();
            InitializeGrid();

            mappingsSource = new BindingSource(this.mappings, null);
            mappingsSource.CurrentChanged += new EventHandler(mappingsSource_CurrentChanged);
            dataGridViewMappings.DataSource = mappingsSource;

            var firstMapping = mappings.FirstOrDefault();
            if (firstMapping != null)
            {
                propertySource = new BindingSource(firstMapping.Properties, null);
            }
            else
            {
                propertySource = new BindingSource(new List<MappingProperty>(), null);
            }

            dataGridViewProperties.DataSource = propertySource;
        }

        private IEnumerable<Type> DetermineTypes()
        {
            Assembly asm = Assembly.Load("Microsoft.Data.Schema.Sql, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
            if (asm != null)
            {
                Type modelElement = Type.GetType("Microsoft.Data.Schema.SchemaModel.IModelElement, Microsoft.Data.Schema, Version=10.0.0.0");

                if (modelElement != null)
                {
                    var matches = asm.GetTypes()
                        .Where(t => t.IsInterface &&
                                    t.GetInterface(modelElement.Name) != null)
                        .OrderBy(t => t.Name)
                        .Select(t => t);

                    return matches.ToList();
                }
            }

            return null;
        }

        private void mappingsSource_CurrentChanged(object sender, EventArgs e)
        {
            if (mappingsSource.Current != null)
            {
                propertySource.DataSource = (mappingsSource.Current as TemplateMapping).Properties;
                propertySource.ResetBindings(false);
            }
            else
            {
                propertySource.DataSource = null;
                propertySource.ResetBindings(false);
            }
        }

        private void InitializeGrid()
        {
            dataGridViewMappings.AutoGenerateColumns = false;

            dataGridViewMappings.Columns.Add(new DataGridViewCheckBoxColumn() { DataPropertyName = "Enabled", HeaderText = "Enabled", Width = 30 });
            DataGridViewComboBoxColumn typeColumn = new DataGridViewComboBoxColumn()
            {
                DataPropertyName = "Type",
                HeaderText = "Type",
                Width = 180,
                CellTemplate = new DataGridViewComboBoxCell()
                {
                    DisplayMember = "Name",
                    ValueMember = "AssemblyQualifiedName",
                    DataSource = objectTypes
                }
            };
            dataGridViewMappings.Columns.Add(typeColumn);

            DataGridViewComboBoxColumn templateColumn = new DataGridViewComboBoxColumn()
            {
                DataPropertyName = "Template",
                HeaderText = "Template",
                Width = 180,
                CellTemplate = new DataGridViewComboBoxCell()
                {
                    DisplayMember = "Name",
                    ValueMember = "Name",
                    DataSource = templates
                }
            };
            dataGridViewMappings.Columns.Add(templateColumn);

            DataGridViewComboBoxColumn projectColumn = new DataGridViewComboBoxColumn()
            {
                DataPropertyName = "Project",
                HeaderText = "Project",
                Width = 180,
                CellTemplate = new DataGridViewComboBoxCell()
                {
                    DisplayMember = "Name",
                    ValueMember = "Name",
                    DataSource = projects
                }
            };
            dataGridViewMappings.Columns.Add(projectColumn);
            dataGridViewMappings.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = "ObjectNameTemplate", HeaderText = "ObjectNameTemplate", Width = 180 });
            dataGridViewMappings.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = "FileNameTemplate", HeaderText = "FileNameTemplate", Width = 180 });
            dataGridViewMappings.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = "Order", HeaderText = "Order", Width = 40 });

            dataGridViewProperties.AutoGenerateColumns = false;

            dataGridViewProperties.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = "Key", HeaderText = "Key", Width = 180 });
            dataGridViewProperties.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = "Value", HeaderText = "Value", Width = 180 });

            dataGridViewProperties.ReadOnly = false;
            dataGridViewProperties.AllowUserToAddRows = true;
            dataGridViewProperties.AllowUserToDeleteRows = true;
        }

        private void buttonOk_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            mappingsSource.AddNew();
        }

        private void buttonRemove_Click(object sender, EventArgs e)
        {
            mappingsSource.Remove(mappingsSource.Current);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            propertySource.AddNew();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            propertySource.Remove(propertySource.Current);
        }

        private void dataGridViewMappings_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            e.ThrowException = false;
        }
    }

    public class Project
    {
        public string Name { get; set; }
    }

    public class Template
    {
        public string Name { get; set; }
    }
}
